package com.kaifamiao.token.servlet;

import com.alibaba.fastjson2.JSONObject;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import org.tinylog.Logger;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

@WebServlet("/generate/token")
public class GenerateTokenServlet extends HttpServlet {

    JWSAlgorithm algorithm = JWSAlgorithm.HS256;
    JOSEObjectType type = JOSEObjectType.JWT;
    private String secret;

    @Override
    public void init() throws ServletException {
        ServletContext sc = this.getServletContext();
        secret = sc.getInitParameter( "secret" );
        if( secret == null || (secret = secret.trim()).isEmpty() ) {
            throw new RuntimeException("未在web.xml中设置secret参数");
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        JWSHeader header = new JWSHeader.Builder(algorithm).type(type).build();
        Logger.trace( header.getParsedBase64URL() );

        String json = JSONObject.toJSONString(Map.of("id", 1001, "name", "阿芳"));
        Payload payload = new Payload( json );
        Logger.trace( payload.toBase64URL() );

        JWSSigner signer;
        try {
            // Create HMAC signer
            signer = new MACSigner(secret);
        } catch (KeyLengthException e) {
            Logger.error(e, "创建签名器失败");
            return;
        }

        JWSObject jwsObject = new JWSObject( header, payload );
        try {
            jwsObject.sign( signer );
        } catch (JOSEException e) {
            Logger.error(e, "签名失败");
            return;
        }

        // 将 JWSObject 格式化为 字符串形式
        String token = jwsObject.serialize();
        PrintWriter out = resp.getWriter();
        out.println( JSONObject.toJSONString( Map.of("token", token) ) );

    }

}
